# Core 방식으로 행 삽입하기

이번 챕터에서는 SQLAlchemy Core 방식으로 데이터를 INSERT 하는 방법을 배웁니다.


# insert() 를 통한 SQL 표현식 구성

먼저 다음처럼 INSERT 구문을 만들 수 있습니다.

>>> from sqlalchemy import insert

#  stmt는 Insert 객체 인스턴스입니다.
>>> stmt = insert(user_table).values(name='spongebob', fullname="Spongebob Squarepants")
>>> print(stmt)
'INSERT INTO user_account (name, fullname) VALUES (:name, :fullname)'

여기서 user_table은 우리가 이전 챕터에서 만든 Table 객체입니다. 우리는 아래처럼 만들었었습니다.

from sqlalchemy import MetaData
from sqlalchemy import Table, Column, Integer, String

metadata = MetaData()
user_table = Table(
    'user_account',
    metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String(30)),
    Column('fullname', String),
)

stmt 를 보면 아직 매개변수가 매핑되지는 않았습니다.
이는 다음처럼 complie() 한 후에 확인할 수 있습니다.

>>> compiled = stmt.compile()
>>> print(compiled.params)
{'name': 'spongebob', 'fullname': 'Spongebob Squarepants'}

# 명령문 실행

이제 위에서 만든 INSERT 구문을 Core 방식으로 실행해봅시다.

>>> with engine.connect() as conn:
...     result = conn.execute(stmt)
...     conn.commit()

# 위 코드는  결과적으로 아래 쿼리를 실행합니다.
BEGIN (implicit)
INSERT INTO user_account (name, fullname) VALUES (?, ?)
[...] ('spongebob', 'Spongebob Squarepants')
COMMIT

conn.execute(stmt) 의 반환 값을 받은 result 에는 어떤 정보가 있을까요?
resultCursorResult (opens new window) 객체입니다.
여기에는 실행 결과물에 대한 여러 정보를 담고있는데, 특히 데이터 행을 담고있는 Row (opens new window) 객체를 들고있습니다.

우리는 방금 데이터를 삽입했고, 이에 대한 결과물로 다음처럼 삽입된 데이터의 기본 키 값을 확인할 수 있습니다.

>>> result.inserted_primary_key  # 이 역시 Row 객체입니다.
(1, )  # 기본 키가 여러 열로 구성될 수 있으므로 튜플로 표현됩니다.

# Connection.execute() 에 INSERT 매개변수 전달하기

위에서는 다음처럼 insertvalues 까지 함께 포함하여 구문울 만들었습니다.

>>> stmt = insert(user_table).values(name='spongebob', fullname="Spongebob Squarepants")

하지만 이 방법 외에도 다음처럼 Connection.execute() 메서드에 매개변수를 전달하여 INSERT 구문을 실행할 수 있습니다.
공식문서에는 이게 좀 더 일반적인 방법이라고 말합니다.

>>> with engine.connect() as conn:
...     result = conn.execute(
...         insert(user_table),
...         [
...             {"name": "sandy", "fullname": "Sandy Cheeks"},
...             {"name": "patrick", "fullname": "Patrick Star"}
...         ]
...     )
...     conn.commit()

공식문서에는 하위 쿼리까지 포함하여 실행시키는 법을 별도의 블락에서 설명하고 있는데, 튜토리얼 내용으로는 다소 적합하지 않다고 판단하여 이 글에는 포함하지 않았습니다. 이 내용이 궁금하신 분들은 원문 링크 (opens new window)를 참고하세요.


# Insert.from_select()

다음처럼 SELECT 하여 받은 행들을 INSERT 하기 위한 쿼리가 필요한 경우가 있습니다.

이런 사례는 예를 들면 다음 코드처럼 작성할 수 있습니다.

>>> select_stmt = select(user_table.c.id, user_table.c.name + "@aol.com")
>>> insert_stmt = insert(address_table).from_select(
...     ["user_id", "email_address"], select_stmt
... )
>>> print(insert_stmt)
"""
INSERT INTO address (user_id, email_address)
SELECT user_account.id, user_account.name || :name_1 AS anon_1
FROM user_account
"""

# Insert.returning()

데이터베이스에서 쿼리 처리 후에 처리된 행의 값을 반환받아야 하는 경우가 있습니다. 이를 RETURNING 문법이라 합니다.
이에 대한 소개 글은 이 블로그 글 (opens new window)을 읽어보시면 좋을거 같습니다.

SQLAlchemy Core에서는 이런 RETURNING 문법을 다음처럼 작성할 수 있습니다.

>>> insert_stmt = insert(address_table).returning(address_table.c.id, address_table.c.email_address)
>>> print(insert_stmt)
"""
INSERT INTO address (id, user_id, email_address)
VALUES (:id, :user_id, :email_address)
RETURNING address.id, address.email_address
"""